﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

using MineLaunch.Controls;
using MineLaunch.ListItem;
using MineLaunch.Windows;
using MineLaunch.Setting;
using System.Collections.ObjectModel;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Threading.Tasks;
using MineLaunch.Plugin;

namespace MineLaunch
{
	public partial class MainWindow : Window
	{
		private void Window_SourceInitialized(object sender, EventArgs e)
		{
			LoadSettings();
			InitializeTargetList();
			InitializeCommandList();

			this.targetListBox.DataContext = TargetList;
			this.commandListBox.DataContext = CommandList;

		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			SaveSettings();
		}

		private void LoadSettings()
		{
			var settingsLocal = SettingsLocal.GetInstance();
			settingsLocal.Load();
			this.Width = settingsLocal.settingsLocal.MainWindowWidth;
			this.Height = settingsLocal.settingsLocal.MainWindowHeight;
			this.Top = settingsLocal.settingsLocal.MainWindowTop;
			this.Left = settingsLocal.settingsLocal.MainWindowLeft;

			this.gridWidth1.Width = new GridLength(settingsLocal.settingsLocal.GridWidth1);
			this.gridHeight1.Height= new GridLength(settingsLocal.settingsLocal.GridHeight1);

			var settingsMain = SettingsMain.GetInstance();
			settingsMain.Load();
			((App)Application.Current).ChangeTheme(((App)Application.Current).Themes[settingsMain.settingsMain.Theme]);
		}

		private void SaveSettings()
		{
			var settingsLocal = SettingsLocal.GetInstance();
			settingsLocal.settingsLocal = new ModelSettingsLocal();
			settingsLocal.settingsLocal.MainWindowWidth = this.Width;
			settingsLocal.settingsLocal.MainWindowHeight = this.Height;
			settingsLocal.settingsLocal.MainWindowTop = this.Top;
			settingsLocal.settingsLocal.MainWindowLeft = this.Left;
			settingsLocal.settingsLocal.GridWidth1 = this.gridWidth1.Width.Value;
			settingsLocal.settingsLocal.GridHeight1 = this.gridHeight1.Height.Value;
			settingsLocal.Save();

			var settingsMain = SettingsMain.GetInstance();
			settingsMain.Save();
		}

		private void InitializeTargetList()
		{
			TargetList.Clear();
			if (!Directory.Exists(SettingsMain.GetInstance().settingsMain.TargetDirectory))
			{
				try
				{
					Directory.CreateDirectory(SettingsMain.GetInstance().settingsMain.TargetDirectory);
				}
				catch { }
			}
			string[] targets = Directory.GetDirectories(SettingsMain.GetInstance().settingsMain.TargetDirectory);
			foreach (string target in targets)
			{
				var targetItem = new TargetListItem();
				targetItem.Content = System.IO.Path.GetFileName(target);
				targetItem.TargetPath = System.IO.Path.GetFileName(target);
				targetItem.MouseDoubleClick += new RoutedEventHandler(targetItem_MouseDoubleClick);
				TargetList.Add(targetItem);
			}
		}

		private void InitializeCommandList()
		{
			var commandSetting = new CommandListItem();
			commandSetting.Content = "設定";
			commandSetting.Description = "設定を変更します。";
			commandSetting.MouseDoubleClick += new RoutedEventHandler(commandSetting_MouseDoubleClick);
			CommandList.Add(commandSetting);

			var commandRefresh = new CommandListItem();
			commandRefresh.Content = "更新";
			commandRefresh.Description = "ターゲット一覧を更新します。";
			commandRefresh.MouseDoubleClick += new RoutedEventHandler(commandRefresh_MouseDoubleClick);
			CommandList.Add(commandRefresh);

			var commandImport = new CommandListItem();
			commandImport.Content = "インポート";
			commandImport.Description = "AppDataのデータをターゲットに追加します。";
			commandImport.MouseDoubleClick += new RoutedEventHandler(commandImport_MouseDoubleClick);
			CommandList.Add(commandImport);

			var commandAddTarget = new CommandListItem();
			commandAddTarget.Content = "ターゲット追加";
			commandAddTarget.Description = "新しくターゲットを追加します。";
			commandAddTarget.MouseDoubleClick += new RoutedEventHandler(commandAddTarget_MouseDoubleClick);
			CommandList.Add(commandAddTarget);

			var commandEditTarget = new CommandListItem();
			commandEditTarget.Content = "ターゲット編集";
			commandEditTarget.Description = "ターゲットを編集します。";
			commandEditTarget.MouseDoubleClick += new RoutedEventHandler(commandEditTarget_MouseDoubleClick);
			CommandList.Add(commandEditTarget);

			var commandDeleteTarget = new CommandListItem();
			commandDeleteTarget.Content = "ターゲット削除";
			commandDeleteTarget.Description = "ターゲットを削除します。";
			commandDeleteTarget.MouseDoubleClick += new RoutedEventHandler(commandDeleteTarget_MouseDoubleClick);
			CommandList.Add(commandDeleteTarget);

			var commandModPatch = new CommandListItem();
			commandModPatch.Content = "MOD導入";
			commandModPatch.Description = "MODを導入します。";
			commandModPatch.MouseDoubleClick += new RoutedEventHandler(commandModPatch_MouseDoubleClick);
			CommandList.Add(commandModPatch);

			var commandModManage = new CommandListItem();
			commandModManage.Content = "MOD管理";
			commandModManage.Description = "MODを管理します。";
			commandModManage.MouseDoubleClick += new RoutedEventHandler(commandModManage_MouseDoubleClick);
			CommandList.Add(commandModManage);

			var commandShowLog = new CommandListItem();
			commandShowLog.Content = "ログ表示";
			commandShowLog.Description = "ログを表示して実行します。";
			commandShowLog.MouseDoubleClick += new RoutedEventHandler(commandShowLog_MouseDoubleClick);
			CommandList.Add(commandShowLog);

			var commandHelp = new CommandListItem();
			commandHelp.Content = "ヘルプ";
			commandHelp.Description = "ヘルプを表示します。";
			commandHelp.IsVisible = false;
			commandHelp.MouseDoubleClick += new RoutedEventHandler(commandHelp_MouseDoubleClick);
			CommandList.Add(commandHelp);

			var pm = new PluginManager();
			pm.LoadPlugins();
			foreach (MLPlugin.PluginBase plugin in pm.GetPluginList())
			{
				var commandPlugin = new PluginListItem();
				commandPlugin.PluginInstance = plugin;
				commandPlugin.Content = plugin.GetContent();
				commandPlugin.Description = plugin.GetDescription();
				commandPlugin.MouseDoubleClick += new RoutedEventHandler(commandPlugin_MouseDoubleClick);
				CommandList.Add(commandPlugin);
			}
		}

		public void commandPlugin_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = targetListBox.SelectedItem as TargetListItem;
			string targetName = "";
			string targetPath = "";
			if (target != null)
			{
				targetName = target.Content;
				targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath);
			}
			var plugin = sender as PluginListItem;
			plugin.PluginInstance.RunCommand(targetName, targetPath);
		}

		private void commandSetting_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var window = new SettingsWindow();
			window.Owner = this;
			window.ShowDialog();
		}

		void commandRefresh_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			InitializeTargetList();
		}

		private void commandImport_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			string appdata = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".minecraft");
			string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, "import", ".minecraft");
			if (!Directory.Exists(appdata))
			{
				MessageBox.Show("Minecraftが存在しません。");
				return;
			}

			this.IsEnabled = false;
			var importTask = Task.Factory.StartNew(() =>
			{
				Common.Common.CopyDirectory(appdata, targetPath, true);
			});
			importTask.ContinueWith(x =>
			{
				this.Dispatcher.BeginInvoke(new Action(() =>
				{
					this.IsEnabled = true;
					InitializeTargetList();
				}));
				MessageBox.Show("インポート完了");
			});
		}

		private void commandAddTarget_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var window = new TextWindow();
			window.Title = "ターゲット追加";
			window.Description.Content = "ターゲットを追加します。";
			window.Owner = this;
			if (window.ShowDialog().Value)
			{
				if (!Common.Common.CanUseFileName(window.Text))
				{
					MessageBox.Show(String.Format("'{0}' は使用出来ない名前です。", window.Text));
					return;
				}
				string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, window.Text);
				Directory.CreateDirectory(targetPath);
				InitializeTargetList();
			}
		}

		private void commandEditTarget_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = targetListBox.SelectedItem as TargetListItem;
			if (target == null) return;
			var window = new TextWindow();
			window.Title = "ターゲット編集";
			window.Description.Content = "ターゲットを編集します。";
			window.Owner = this;
			window.Text = target.TargetPath;
			if (window.ShowDialog().Value)
			{
				string sourcePath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath);
				string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, window.Text);
				if (!Common.Common.CanUseFileName(window.Text))
				{
					MessageBox.Show(String.Format("'{0}' は使用出来ない名前です。", window.Text));
					return;
				}
				if (Directory.Exists(targetPath))
				{
					MessageBox.Show(String.Format("'{0}' は既に使用されています。", window.Text));
					return;
				}
				Directory.Move(sourcePath, targetPath);
				InitializeTargetList();
			}
		}

		private void commandDeleteTarget_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = targetListBox.SelectedItem as TargetListItem;
			if (target == null) return;
			if (MessageBox.Show(String.Format("{0} を削除しますか？", target.TargetPath), "ターゲット削除", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath);
				if (Directory.Exists(targetPath))
				{
					Directory.Delete(targetPath, true);
				}
				InitializeTargetList();
			}
		}

		private void commandShowLog_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = targetListBox.SelectedItem as TargetListItem;
			if (target == null) return;
			string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath);
			var window = new LogViewWindow();
			window.Show();
			window.Run(targetPath);
		}

		private void commandModPatch_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			string mcpatcherPath = SettingsMain.GetInstance().settingsMain.MCPatcherPath;
			if(!File.Exists(mcpatcherPath))
			{
				MessageBox.Show("MCPatcherのパスが設定されていません。");
				return;
			}
			var target = targetListBox.SelectedItem as TargetListItem;
			if (target == null) return;
			string minecraftPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath, ".minecraft");
			Process.Start(mcpatcherPath, String.Format("-mcdir {0}", minecraftPath));
		}

		public void commandModManage_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = targetListBox.SelectedItem as TargetListItem;
			if (target == null) return;
			string mlConfigPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath, ".minecraft", "config", "ModLoader.cfg");
			if (File.Exists(mlConfigPath))
			{
				var window = new ModManagerWindow(mlConfigPath);
				window.Owner = this;
				window.ShowDialog();
			}
		}

		private void commandHelp_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var window = new HelpWindow();
			window.Owner = this;
			window.ShowDialog();
		}

		public void targetItem_MouseDoubleClick(object sender, RoutedEventArgs e)
		{
			var target = sender as TargetListItem;
			if (target == null) return;
			string targetPath = Path.Combine(SettingsMain.GetInstance().settingsMain.TargetDirectory, target.TargetPath);
			if (!Directory.Exists(targetPath))
			{
				Directory.CreateDirectory(targetPath);
			}
			var minecraftExePath = Path.Combine(SettingsGlobal.MinecraftExePath);
			var settings = SettingsMain.GetInstance().settingsMain;
			if (!File.Exists(settings.JavaPath))
			{
				MessageBox.Show("java.exeのパスが設定されていません。");
				return;
			}
			if (!File.Exists(minecraftExePath))
			{
				MessageBox.Show("Minecraft.exeが存在しません。\nMineLaunch.exeと同じフォルダに置いてください。");
				return;
			}
			var process = new Process();
			ProcessStartInfo processInfo = new ProcessStartInfo();
			processInfo.FileName = settings.JavaPath;
			if (settings.IsAutoLogin)
			{
				string passworld = Common.Common.Decrypt(settings.MinecraftPassword);
				processInfo.Arguments = String.Format("-Xms{0}m -Xmx{1}m -jar {2} {3} {4}", settings.Xms, settings.Xmx, minecraftExePath, settings.MinecraftID, passworld);
			}
			else
			{
				processInfo.Arguments = String.Format("-Xms{0}m -Xmx{1}m -jar {2}", settings.Xms, settings.Xmx, minecraftExePath);
			}
			processInfo.UseShellExecute = false;
			processInfo.EnvironmentVariables.Remove("APPDATA");
			processInfo.EnvironmentVariables.Add("APPDATA", targetPath);
			process.StartInfo = processInfo;
			processInfo.CreateNoWindow = true;
			process.Start();

			Common.Common.ResizeMinecraftWindow();
		}
	}
}
